Apple II
File Type Notes
_____________________________________________________________________________
                                                  Developer Technical Support
File Type:         $D8 (216)
Auxiliary Type:    $0002

Full Name:     Apple IIGS Sampled Instrument File
Short Name:    ASIF File

Written by:    John Worthington & Matt Deatherage                March 1989

Files of this type and auxiliary type contain instruments in the Apple IIGS 
Sampled Instrument Format (ASIF).
_____________________________________________________________________________

The Apple IIGS Sampled Instrument Format (ASIF) is the standard format used 
for storing Apple IIGS Sampled Instruments on disk.  All sampled instruments 
supplied by Apple for the Apple IIGS Note Synthesizer will use this format.  
Likewise, all utilities supporting Note Synthesizer sampled instruments will 
also use this format.

ASIF is designed around the needs of the current Apple IIGS Note Synthesizer 
and Apple IIGS sound hardware.  While the format of ASIF (especially INST 
chunks) is greatly influenced by the Note Synthesizer, the information may be 
sufficient for other sampled sound synthesizers to accurately render the 
sound.

Most instrument files for the Apple IIGS have a ProDOS file type of $D6.  ASIF 
files are instead identified as file type $D8, auxiliary type $0002 because of 
their sampled nature.  All other instruments for the the Apple IIGS will be 
identified by file type $D6.

Note:    Earlier ASIF documentation, not widely circulated, defined 
         ASIF files as file type $CA, auxiliary type $8000.  As documented 
         in this Note, ASIF has been reassigned to file type $D8 and 
         auxiliary type $0002.  Applications which read files based on the 
         old file type and auxiliary type should not perform adversely, 
         since no other application should be creating files with that 
         combination.  However, we strongly urge developers to create ASIF 
         files with file type $D8 and auxiliary type $0002 only.  We 
         further encourage developers to revise existing programs to use 
         this new assignment at their earliest convenience.

ASIF files conform to the "EA IFF 85" Standard for Interchange Format Files 
developed by Electronic Arts.  Electronic Arts additionally has some public 
domain code available for reading and writing IFF files.

ASIF is provided more for compatibility than for interchange.  It is a highly 
Apple IIGS specific file format.  Those wishing the highest level of sampled 
sound compatibility across programs and CPUs should use Audio Interchange File 
Format (Audio IFF).  Audio IFF is documented in Apple II File Type Note for 
file type $D8, auxiliary type $0000.

This Note defines the required chunks INST and WAVE, as well as the optional 
("NAME"), copyright ("(c) "), author ("AUTH"), and annotation ("ANNO") chunks.  
These are all "standard" chunks.  Additional chunks for private or future 
needs may be added later.  Figure 1, located at the end of this Note, 
illustrates the ASIF format in a box diagram.


Required Data Chunks

An ASIF file consists of a single FORM ASIF, which contains one and only one 
WAVE chunk and one or more INST chunks.  Each ASIF file defines at least one 
instrument.

INST chunks contain all of the Note Synthesizer specific information needed to 
define an instrument, exclusive of the actual wave form.  The information in 
the INST chunk defines the characteristics of an instrument such as the 
envelope, pitch range, and maximum pitch bend.  There must be at least one 
INST chunk for each instrument in the ASIF file.

WAVE chunks contain the waveforms for a given instrument.  A WAVE chunk may 
contain waveforms used by more than one instrument.  In most cases, the 
waveforms used by an application will be merged into a single 64K block that 
is loaded into DOC RAM when the application is launched.  In this case, there 
would be several INST chunks referring to that single WAVE chunk.  Most music 
applications will probably store instruments one to a file, which is the 
preferred way of distributing ASIF instruments.

Note:    The length of any chunk must be even.  If a chunk has an odd 
         length, a pad byte of $00 must be added to the end of the chunk.  
         The pad byte, if present, should never have a value other than 
         $00.


The FORM Chunk

ckID      4 Bytes      The ID for this chunk.  These four bytes must be 
                       "FORM."
ckSize    Rev. Long    The length of this chunk, excluding ckSize and 
                       cdID.  You may think of this value as the 
                       offset to the end of the chunk.  Note that 
                       this is a Reverse Long; the bytes are 
                       stored high byte first.
ckType    4 Types      The type of chunk.  These four bytes must be 
(chunks...)            "ASIF."

Immediately following the 12-byte FORM chunk header are the data chunks of the 
ASIF file.  There most be one and only one WAVE chunk, and at least one INST 
chunk.  Optionally there may be name ("NAME"), copyright ("(c) "), author 
("AUTH"), or annotation ("ANNO") chunks.  All data chunks are part of the 
larger FORM chunk, referred to as the FORM ASIF because of the ID and Type of 
this chunk.


The INST Chunk

ckID      4 Bytes      The ID for this chunk.  These four bytes must be 
                       "INST."
ckSize    Rev. Long    The length of this chunk, excluding ckSize and 
                       cdID.  You may think of this value as the 
                       offset to the end of the chunk.  Note that 
                       this is a Reverse Long; the bytes are 
                       stored high byte first.
InstName  String       A Pascal String containing the name of the 
                       instrument referred to by this INST block.  
                       This string should be used as the display 
                       name of the instrument.

Note:  The length byte of InstName is also referred to as INameLength.

SampleNum   Word       The number of the sample in the WAVE chunk to 
                       which this instrument refers.
Envelope    8 InstSegs Eight linear InstSegs defining the 
                       instrument's envelope.

The InstSeg is a three-byte linear segment that describes a level and a 
slope.  The level is called the breakpoint and represents the linear 
amplitude of the sound.  The slope is described by an increment added or 
subtracted from the current level at the update rate.  Regardless of the 
increment, the breakpoint will never be exceeded.  All ASIF instruments 
assume an update rate of 200 Hz.  The increment is a two-byte fixed 
pointer; that is, the lower eight bits represent a fraction.  Thus when 
the increment is one, it represents 1/256.  In this case, the increment 
would have to be added 256 times (1.28 seconds) to cause the level to go 
up by 1.  At a 200 Hz update rate each increment takes 5 milliseconds.  
If an application wishes to use an update rate other than 200 Hz, the 
envelope must be scaled as necessary.  If the envelope is not scaled, 
the instrument will not sound correct.

The breakpoint is a byte between 0 and 127 ($00 and $7F).  It should 
represent sound level in a logarithmic scale:  every 16 steps change the 
amplitude by 6 dB.

Therefore the envelope is composed of eight InstSegs:

stage1    Byte       Breakpoint 1
          2 Bytes    Increment 1
stage2    Byte       Breakpoint 2
          2 Bytes    Increment 2
stage3    Byte       Breakpoint 3
          2 Bytes    Increment 3
stage4    Byte       Breakpoint 4
          2 Bytes    Increment 4
stage5    Byte       Breakpoint 5
          2 Bytes    Increment 5
stage6    Byte       Breakpoint 6
          2 Bytes    Increment 6
stage7    Byte       Breakpoint 7
          2 Bytes    Increment 7
stage8    Byte       Breakpoint 8
          2 Bytes    Increment 8

Increment 1 is used to go from the initial level of 0 up to the level of 
breakpoint 1.  Increment 2 is used to go from breakpoint 1 to breakpoint 
2, and so on.  The sustain level of the envelope, if there is one, is 
created by setting the increment to zero, causing the envelope to get 
stuck on that level.  The last segment used for release should always 
have a breakpoint of zero, so the sound eventually reaches silence.  
Unused segments should have a zero breakpoint and a non-zero increment.

ReleaseSegment     Byte      Specifies the release segment of the 
                             envelope.  This must be a number from 1 to 
                             7.  The release may take several segments 
                             to get to zero.  The last segment should 
                             always be zero.
PriorityIncrement  Byte      A number that will be subtracted from the 
                             generator priority when the envelope 
                             reaches the sustain segment.  The sustain 
                             segment is the first segment with a zero 
                             increment.  When the release segment is 
                             reached, the priority is cut in half.  The 
                             priority of each generator is also 
                             decremented by one each time a new 
                             generator is allocated.  This causes older 
                             notes to be preferred for stealing.
PitchBendRange     Byte      The number of semitones that the pitch will 
                             be raised when the pitchwheel reaches 127 
                             (the center value is 64).  The legal 
                             values for PitchBendRange are 1, 2, and 4.
VibratoDepth       Byte      The initial fixed depth of vibrato, ranging 
                             from 0 to 127.  Vibrato is a triangular-
                             shaped Low Frequency Oscillator (LFO) 
                             modulating the pitch of both oscillators 
                             in a generator.  A VibratoDepth of zero 
                             turns the vibrator mechanism off, which 
                             saves some CPU time (since vibrato is 
                             implemented in software).
VibratoSpeed       Byte      Controls the rate of the vibrato LFO.  It can 
                             be any byte value, although the range from 
                             5 to 20 is most useful.  The frequency 
                             range is linear, in 0.2 Hz steps.
UpdateRate         Byte      Unused; set to zero.  Previous versions of ASIF 
                             listed this byte as the update rate in .4 
                             Hz, but a one-byte field is not large 
                             enough to provide suitable resolution (102 
                             Hz is the maximum allowed), much less the 
                             standard Note Synthesizer value of 200 Hz 
                             (the byte would have to hold the value 
                             500; not an easy task for a byte).  All 
                             ASIF instruments are assumed to have an 
                             update rate of 200 Hz.
AWaveCount         Byte      The number of waves in the following AWaveList.  
                             There can be up to 255 waves in the 
                             AWaveList.
BWaveCount         Byte      The number of waves in the following BWaveList.  
                             There can be up to 255 waves in the 
                             BWaveList.
AWaveList      AWaveCount    Waves.
BWaveList      BWaveCount    Waves.

The WaveList structure is a variable-length array where each entry is 
six bytes long.  The information is particular to the DOC, and the 
developer should refer to the DOC information in the Apple IIGS Hardware 
Reference and the Apple IIGS Toolbox Reference Update when creating 
instruments.  Each six-byte entry represents a waveform and contains 
information about the allowable pitch range of the waveform.  This means 
that the waves can be "multi-sampled" across an imaginary keyboard.  
When a note is played, WaveListA and WaveListB will be examined, and one 
waveform will be picked and assigned to each oscillator.

Each wave in a WaveList has the following 6-byte format:

TopKey             Byte      The highest MIDI semitone this waveform will play.  
                             The Note Synthesizer will examine the 
                             TopKey field of each waveform until it 
                             finds one greater than or equal to the 
                             note it is trying to play.  The items in 
                             the WaveList should be in order of 
                             increasing TopKey values.  The last wave 
                             should have a TopKey value of 127.  The 
                             TopKey value is the split point between 
                             the waveforms.

The next three bytes will be stuffed into the DOC registers:

WaveAddress        Byte      The high byte of the waveform address.  Note 
                             that the value selected for WaveAddress 
                             should assume that the waveform starts in 
                             page zero.  When the waveform is actually 
                             placed in DOC RAM, the values must be 
                             adjusted as appropriate.  As an example, 
                             for a waveform starting at $8000 in DOC 
                             RAM, this value would be $80.
WaveSize           Byte      Sets both the size of the wavetable and the 
                             frequency resolution.
DOCMode            Byte      Placed in the DOCs Mode register.  The interrupt-
                             enable should always be zero.

                             Some ways this may be used are:
                             Synthesizer ($00), where both oscillators 
                             (A and B) run in free run mode
                             Sample, no loop:  Oscillator A in swap 
                             mode ($06) and oscillator B in one-shot 
                             halted mode ($03).  Oscillator A will play 
                             its wave once and start Oscillator B, 
                             which will play its wave to the end once 
                             and stop.
                             Sampled with loop:  Oscillator A in swap 
                             mode ($06), and Oscillator B in free-run 
                             halted mode ($01).  Oscillator A will play 
                             its wave once and then start Oscillator B, 
                             which will play continuously until the 
                             note ends.

                             The high nibble of the DOCMode is the channel
                             number.  This must be set correctly for stereo
                             output.  While all of the currently available
                             stereo cards will map even-numbered channels to 
                             the right and odd-numbered channels to the 
                             left, software should use channel 0 for 
                             right and channel 1 for left.  This will 
                             ensure compatibility with cards that 
                             provide more than two channels of output.  
                             If you are not designing stereo 
                             instruments, always set the channel to 
                             zero.
RelPitch           Word      Used to tune the waveform.  This will compensate 
                             for different sample rates and waveform 
                             sizes.  The high byte is in semitones, but 
                             can be a signed number.  The low byte is 
                             in 1/256 semitone increments.  Note that 
                             the low byte is first in memory; this is a 
                             regular 65816 Word.  A setting of zero is 
                             the default for sounds that gave one cycle 
                             per page of waveform memory.

The WaveList structure is designed to give greater flexibility in 
creating realistic instrumental timbres.  It allows "multi-sampling" 
with different samples of sounds on different ranges of pitch.  It 
allows mixing of various sized wave forms, with different tuning on each 
semitone, to allow separate tuning of each note.  This is one way to 
duplicate special tuning systems like "just temperament."  The wave 
pointers need not be different in this case, just the RelPitch fields.

Tuning is accurate to 1/128 of a semitone in the Note Synthesizer, 
subject to the resolution setting of the DOC.  For accurate tuning on 
lower notes, it may be necessary to use higher settings in the DOC 
resolution register.

Note:    The Audio Interchange File Format (Audio IFF) also has a 
         chunk named "INST" which will appear to a standard IFF reader the 
         same as the ASIF "INST" chunk.  To tell the two apart, check the 
         ckSize field.  The Audio IFF "INST" chunk will always have ckSize 
         of 20 bytes, and the ASIF "INST" chunk will never have a chunk 
         size of 20 bytes.


The WAVE chunk

ckID          4 Bytes        The ID for this chunk.  These four bytes must be 
                             "WAVE."
ckSize        Rev. Long      The length of this chunk, excluding ckSize and 
                             cdID.  You may think of this value as the 
                             offset to the end of the chunk.  Note that 
                             this is a Reverse Long; the bytes are 
                             stored high byte first.
WaveName      String         A Pascal String containing the name of the 
                             waveform referred to by this WAVE block. 

Note:  The length byte of WaveName is also referred to as WaveNameLen.

WaveSize      Word           The size of the waveform WaveData, in bytes.  
                             WaveSize may be any value from $0000 to 
                             $FFFF.  This is a zero-based counter; 
                             WaveData that is one byte long would 
                             result in a WaveSize of $0000.  This 
                             allows full 64K WaveData entries.
NumSamples    Word           The number of different sounds in this WAVE 
                             chunk.  NumSamples describes the number of 
                             entries in SampleTable.  Note that this is 
                             not necessarily the number of instruments.  
                             Although not required, there should be a 
                             WaveList entry in an INST chunk for each 
                             entry in the SampleTable.
SampleTable   NumSamples     Samples.

SampleTable is a table of the waveforms corresponding to different 
"samples".  Each entry in SampleTable is 12 bytes long.  Each sample 
entry is defined as follows:

Location      Word           The byte offset to the waveform from the beginning 
                             of the WAVE chunk.
Size          Word           The size of the waveform in 256-byte pages.  Size is 
                             specified in pages since the sample size 
                             passed to the DOC must be in pages.
OrigFreq      Fixed          The original frequency that was sampled, in 
                             hertz.  For example, if A440 was sampled, 
                             the value of this field would be 440.00.  
                             A value of zero in this field means that 
                             the original frequency of the sample is 
                             unknown.
SampRate      Fixed          The sample rate used to generate this sample, in 
                             hertz.  A value of zero in this field 
                             means that the original sample rate is 
                             unknown.

There are NumSamples of these sample entries in the SampleTable.

WaveData      WaveSize Bytes The actual waveform.  The DOC uses 
                             samples in an eight-bit linear format.  A 
                             value of $80 is considered to be a zero 
                             crossing.  Positive values are greater 
                             than $80; negative values are less than 
                             $80.  Although WaveData may contain zeros 
                             as oscillator control values, it should 
                             never contain a zero value as a sample 
                             value since this halts the oscillator.


Optional Data Chunks

There are currently three types of optional data chunks.  These chunks may be 
included in an ASIF file if desired.  They are considered part of the set of 
"standard" chunks in the Electronic Arts "EA IFF 85" definition.


The NAME Chunk

This chunk names the instrument of collection of instruments defined in the 
ASIF file.  This chunk may be used to supply a display name for a collection 
of instruments.  This can be useful since IFF programs know about the NAME 
chunk, but may not know about the name field in INST or WAVE chunks.

ckID          4 Bytes        The ID for this chunk.  These four bytes must be 
                             "NAME."
ckSize        Rev. Long      The length of this chunk, excluding ckSize and 
                             cdID.
Name          Bytes          ASCII characters ($20-$7F) representing the name.  
                             There should be ckSize characters.

The AUTH Chunk

ckID          4 Bytes        The ID for this chunk.  These four bytes must be 
                             "AUTH."
ckSize        Rev. Long      The length of this chunk, excluding ckSize and 
                             cdID.
author        Bytes          ASCII characters ($20-$7F) representing the name of 
                             the author of the voices or collection of 
                             voices.  There should be ckSize 
                             characters.

The "(c) " Chunk

ckID          4 Bytes        The ID for this chunk.  These four bytes must be 
                             "(c) ."
ckSize        Rev. Long      The length of this chunk, excluding ckSize and 
                             cdID.  You may think of this value as the 
                             offset to the end of the chunk.
notice        Bytes          ASCII characters ($20-$7F) representing a copyright 
                             notice for the voice or collection of 
                             voices.  There should be ckSize 
                             characters.

The ANNO Chunk

ckID          4 Bytes        The ID for this chunk.  These four bytes must be 
                             "ANNO."
ckSize        Rev. Long      The length of this chunk, excluding ckSize and 
                             cdID.  You may think of this value as the 
                             offset to the end of the chunk.  Note that 
                             this is a Reverse Long; the bytes are 
                             stored high byte first.
author        Bytes          ASCII characters ($20-$7F) representing the name of 
                             the author of the voices or collection of 
                             voices.  There should be ckSize 
                             characters.


Other Chunk Types

There are many types of IFF chunks other than those described in this 
document.  New chunks may be added to ASIF files in the future.  If an 
application encounters a chunk it doesn't recognize when reading an ASIF file, 
it should ignore it.  Note that all chunks should be preserved when copying an 
IFF file.

Figure 1 illustrates a sample ASIF file as a box diagram.

            --------------------------------------------
            |        'FORM'            76112           |
            |                                          |
            |  --------------------------------------  |
            |  |     'ASIF'                         |  |
            |  |                                    |  |
            |  |  --------------------------------  |  |
            |  |  |  'NAME'            9         |  |  |
            |  |  |  "Jazz Band"                 |  |  |
            |  |  --------------------------------  |  |
            |  |  --------------------------------  |  |
            |  |  |  'INST'            50        |  |  |
            |  |  |  3"Sax"0 ...                 |  |  |
            |  |  --------------------------------  |  |
            |  |  --------------------------------  |  |
            |  |  |  'INST'            82        |  |  |
            |  |  |  5"Drums"1 ...               |  |  |
            |  |  --------------------------------  |  |
            |  |  --------------------------------  |  |
            |  |  |  'INST'            51        |  |  |
            |  |  |  4"Bass"2 ...                |  |  |
            |  |  --------------------------------  |  |
            |  |  --------------------------------  |  |
            |  |  |  'INST'            112       |  |  |
            |  |  |  5"Piano"3 ...               |  |  |
            |  |  --------------------------------  |  |
            |  |  --------------------------------  |  |
            |  |  |  'INST'            65656     |  |  |
            |  |  |  10"Jazz Stuff" 65535 4 ...  |  |  |
            |  |  --------------------------------  |  |
            |  --------------------------------------  |
            --------------------------------------------

                     Figure 1-Sample ASIF File


Further Reference
_____________________________________________________________________________
    o    Apple IIGS Toolbox Reference Update
    o    Advanced Sampler's Guide (Ensoniq Corporation)
    o    "Programming the Ensoniq Mirage," Keyboard Magazine, November 1986
    o    "EA IFF 85" Standard for Interchange Format Files, Electronic Arts, 
         Inc.  Describes the underlying conventions for all IFF files. 